package com.yungu.swift.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.yungu.swift.assets.driver.model.dto.CarDto;
import com.yungu.swift.assets.driver.model.dto.CarModelValuationDto;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.model.dto.DriverStatusCycleDto;
import com.yungu.swift.assets.driver.model.vo.DriverVo;
import com.yungu.swift.assets.driver.service.CarModelValuationService;
import com.yungu.swift.assets.driver.service.CarService;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.driver.service.DriverStatusCycleService;
import com.yungu.swift.assets.passenger.model.dto.PassengerCouponDto;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.model.param.ApiPasPayCouponParam;
import com.yungu.swift.assets.passenger.model.vo.PassengerVo;
import com.yungu.swift.assets.passenger.service.PassengerCouponService;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.autoconfig.lock.RedisLock;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.model.api.ApiPageParam;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.lbs.model.DriverLocation;
import com.yungu.swift.lbs.model.dto.LatLngDto;
import com.yungu.swift.lbs.model.param.TrsearchParam;
import com.yungu.swift.lbs.model.vo.DrivingNearestVo;
import com.yungu.swift.lbs.model.vo.TrackVo;
import com.yungu.swift.lbs.service.DistanceService;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.config.ApplicationConfig;
import com.yungu.swift.order.consts.Constants;
import com.yungu.swift.order.dao.OrderMapper;
import com.yungu.swift.order.helper.OrderHelper;
import com.yungu.swift.order.model.dto.OrderDetailDto;
import com.yungu.swift.order.model.dto.OrderDto;
import com.yungu.swift.order.model.dto.OrderFareDto;
import com.yungu.swift.order.model.param.ApiOrderListParam;
import com.yungu.swift.order.model.param.ApiOrderNoAnswerCancelParam;
import com.yungu.swift.order.model.param.SecretNoParam;
import com.yungu.swift.order.model.vo.AllPassengerOrderVo;
import com.yungu.swift.order.model.vo.ApiDriverOrderVo;
import com.yungu.swift.order.model.vo.ApiOrderInfoVo;
import com.yungu.swift.order.model.vo.JsonOrderDetailVo;
import com.yungu.swift.order.model.vo.JsonOrderListVo;
import com.yungu.swift.order.model.vo.PayVo;
import com.yungu.swift.order.processor.CommissionProcessor;
import com.yungu.swift.order.processor.CrosstownOrderProcessor;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.order.service.OrderFareService;
import com.yungu.swift.order.service.OrderSecretNoService;
import com.yungu.swift.order.service.OrderService;
import com.yungu.swift.order.service.OrderTrackMileageService;
import com.yungu.swift.order.service.RefundService;
import com.yungu.swift.order.thread.driver.status.DriverStatusCycleRunnable;
import com.yungu.swift.order.thread.inform.InformThreadPoolUtil;
import com.yungu.swift.order.thread.inform.OrderEvent;
import com.yungu.swift.order.thread.inform.OrderStatusInformThread;
import com.yungu.swift.order.utils.CommonUtils;
import com.yungu.swift.order.utils.PolylineUtils;
import com.yungu.swift.order.utils.SendMessageUtils;
import com.yungu.swift.order.utils.ThreadExecutorUtils;
import com.yungu.swift.socket.communication.message.UploadLocationMessage;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.system.finance.service.FinanceOrderService;
import com.yungu.swift.system.sys.model.dto.SysBusinessOrganizationDto;
import com.yungu.swift.system.sys.service.SysAccountPassengerService;
import com.yungu.swift.system.sys.service.SysBusinessOrganizationService;
import com.yungu.swift.utils.AESUtils;
import com.yungu.swift.utils.DateUtils;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.yungu.swift.constants.CommonConstant.BUSINESS_TYPE_PARCEL;
import static com.yungu.swift.constants.CommonConstant.BUSINESS_TYPE_POOL;
import static com.yungu.swift.constants.OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_SNATCH;
import static com.yungu.swift.constants.OrderConstant.ORDER_CLOSE_STATUS_NORMAL;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_ARRIVE_POINT;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_COMPLETED;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_DRIVER_DEPARTURE;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_INIT;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_PASSENGER_ABOARD;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_PASSENGER_PAY;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_STARTED;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_SUB_OK;
import static com.yungu.swift.constants.OrderConstant.ORDER_JOIN_STATUS_WAIT_START;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_DOING;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_DONE;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_INITIAL;
import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_PAYED;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_ARRIVE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_ARRIVED;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_CONFIRM;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_DRIVER_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_DRI_CANCEL_WAIT_FREE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_FARE_CONFIRM;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_GO;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_NO_ANSWER;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PASSENGER_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PASS_CANCEL_CONFIRM_FREE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PASS_CANCEL_GO_FREE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PASS_CANCEL_WAIT_FREE;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PAY_WAIT_DRI_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_PAY_WAIT_PASS_CANCEL;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_START;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_WAIT;
import static com.yungu.swift.order.consts.Constants.HOMEPAGE_ORDER_STATUS_NULL;
import static com.yungu.swift.order.helper.OrderHelper.fillOrderInfo;
import static com.yungu.swift.order.helper.OrderHelper.findOrder;
import static com.yungu.swift.order.helper.OrderHelper.findOrderDetail;
import static com.yungu.swift.order.helper.OrderHelper.getCrosstownTracePoint;
import static com.yungu.swift.order.helper.OrderHelper.isOrderCanceled;
import static com.yungu.swift.order.helper.OrderHelper.saveOrUpdate;
import static com.yungu.swift.order.helper.OrderHelper.updateOrderStaticDataOnConfirmFare;
import static com.yungu.swift.order.helper.OrderHelper.uploadTextResult;
import static com.yungu.swift.order.helper.OrderPushHelper.buildReportInfo;
import static com.yungu.swift.order.helper.OrderPushHelper.passengerEmergencyPush;
import static com.yungu.swift.order.helper.OrderPushHelper.pushListOrder2Pas;
import static com.yungu.swift.order.helper.OrderPushHelper.pushOrder2Dri;
import static com.yungu.swift.order.helper.OrderPushHelper.pushOrder2Pas;
import static com.yungu.swift.order.model.enums.OrderErrorEnum.GRAB_ERROR_1100;
import static com.yungu.swift.order.service.OrderAssignService.ASSIGN_DRIVER_LOCK;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_ARRIVE_DESTINATION;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_ARRIVE_PICK_UP_LOCATION;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_CANCEL;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_CONFIRM_FARE;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_SET_OUT;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_DRIVER_START_SERVICE;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_OVER_TIME_CANCEL;
import static com.yungu.swift.socket.push.model.PushContent.ORDER_PASSENGER_CANCEL;

@Slf4j
@Service
public class OrderServiceImpl extends BaseServiceImpl<OrderDto> implements OrderService {

    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderFareService orderFareService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderSecretNoService orderSecretNoService;
    @Autowired
    private OrderTrackMileageService orderTrackMileageService;
    @Autowired
    private CommissionProcessor commissionProcessor;
    @Autowired
    private RefundService refundService;
    @Autowired
    private CrosstownOrderProcessor crosstownOrderProcessor;
    @Autowired
    private RedisLock redisLock;

    @Reference
    private CarModelValuationService carModelValuationService;
    @Reference
    private DriverService driverService;
    @Reference
    private PassengerService passengerService;
    @Reference
    private CarService carService;
    @Reference
    private PassengerCouponService passengerCouponService;
    @Reference
    private LocationService locationService;
    @Reference
    private DistanceService distanceService;
    @Reference
    private DriverStatusCycleService driverStatusCycleService;
    @Reference
    private FinanceOrderService financeOrderService;
    @Reference
    private SysAccountPassengerService sysAccountPassengerService;
    @Reference
    private PushService pushService;
    @Reference
    private SysBusinessOrganizationService sysBusinessOrganizationService;

    @Override
    protected IMapper<OrderDto> getMapper() {
        return orderMapper;
    }


    @Override
    public ResponseData<String> saveOrderInfo(OrderDto orderDto, OrderDetailDto orderDetailDto, OrderFareDto orderFareDto) {
        try {
            return ResponseData.buildSuccessResponse(OrderHelper.saveOrderInfo(orderDto, orderDetailDto, orderFareDto));
        } catch (Exception e) {
            log.error("OrderService saveOrderInfo error.orderUuid:{}", orderDto.getUuid());
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存失败");
    }

    @Override
    public ResponseData<JsonOrderDetailVo> getOrderDetail(String uuid, String driverUuid) {
        List<JsonOrderDetailVo> result = orderMapper.listOrderDetail(MapUtils.build("uuid", uuid));
        if (CollectionUtils.isEmpty(result)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单信息失败");
        }
        // 检索订单信息
        JsonOrderDetailVo jsonOrderDetailVo = result.get(0);
        if (StringUtils.isNotEmpty(driverUuid)) {
            jsonOrderDetailVo.setActualDriverUuid(driverUuid);
        }
        if (jsonOrderDetailVo != null) {
            //补充订单中的乘客和司机信息
            fillOrderInfo(jsonOrderDetailVo);
            Date date = new Date();
            //发单正序
            jsonOrderDetailVo.setCountdown(date.getTime() - jsonOrderDetailVo.getCreateOn().getTime());
            // 如果是预约订单，且行程已确定
            if (jsonOrderDetailVo.getTypeTime().compareTo(CommonConstant.TYPE_TIME_APPIONT) == 0
                    && ORDER_STATUS_CONFIRM.compareTo(jsonOrderDetailVo.getSubStatus()) == 0) {
                jsonOrderDetailVo.setCountdown(jsonOrderDetailVo.getDeparTime().getTime() - date.getTime());
            }
            //增加是否超过24小时
            jsonOrderDetailVo.setOverTime(0);
            if (jsonOrderDetailVo.getDeparTime() != null && DateUtils.compareByDay(date, jsonOrderDetailVo.getDeparTime(), 1)) {
                jsonOrderDetailVo.setOverTime(1);
            }
            // 如果订单有确定司机的情况下，做以下判断
            if (jsonOrderDetailVo.getDriver() != null && !StringUtils.isEmpty(jsonOrderDetailVo.getDriver().getUuid())) {
                // （预约单）司机是否可以出发去接乘客
                // 当该订单是最近一条预约订单，且距离出发时间1小时内时才可以
                Map<String, Object> srhMap = MapUtils.build(3);
                srhMap.put("actualDriverUuid", jsonOrderDetailVo.getDriver().getUuid());
                srhMap.put("typeTime", CommonConstant.TYPE_TIME_APPIONT);
                // 检索司机所有进行中预约订单
                List<JsonOrderListVo> listOrderDoing = orderMapper.queryOrderDoing(srhMap);
                // 默认值：不可以出发去接乘客
                jsonOrderDetailVo.setCanPickUp(0);
                // 如果存在进行中订单
                if (listOrderDoing != null && listOrderDoing.size() > 0) {
                    // 该订单是最近一条预约订单
                    if (listOrderDoing.get(0) != null && uuid.equals(listOrderDoing.get(0).getUuid())) {
                        // 距离出发时间1小时内
                        if (jsonOrderDetailVo.getDeparTime().getTime() - date.getTime() <= 60 * 60 * 1000) {
                            // 可以出发去接乘客
                            jsonOrderDetailVo.setCanPickUp(1);
                        }
                    }
                }
                // 司机是否可以催促乘客付款
                // 当乘客未付款超过10分钟可按
                // 默认值：不可以催促乘客付款
                jsonOrderDetailVo.setCanHurryPay(0);
                if (ORDER_MAIN_STATUS_DONE.compareTo(jsonOrderDetailVo.getMainStatus()) == 0) {
                    Map<String, Object> fareMap = MapUtils.build(1);
                    fareMap.put("orderUuid", uuid);
                    OrderFareDto orderFareDto = orderFareService.get(fareMap).getData();
                    // 当乘客未付款超过10分钟可按
                    if (orderFareDto != null && orderFareDto.getArriveTime() != null
                            && (date.getTime() - orderFareDto.getArriveTime().getTime() > 10 * 60 * 1000)) {
                        jsonOrderDetailVo.setCanHurryPay(1);
                    }
                }
            }
            //日租半日租拼接订单标题
            if (CommonConstant.TYPE_TIME_DAILY_RENTAL == jsonOrderDetailVo.getTypeTrip() || CommonConstant.TYPE_TIME_HALF_DAILY_RENTAL == jsonOrderDetailVo.getTypeTrip()) {
                CarModelValuationDto rentFareRuleDto = carModelValuationService.get(MapUtils.build("uuid", jsonOrderDetailVo.getCarModelValuationUuid())).getData();
                if (rentFareRuleDto != null) {
                    jsonOrderDetailVo.setTitle("包车" + rentFareRuleDto.getStartDuration() / 60 + "小时");
                }
            }
            //播报详情
            jsonOrderDetailVo.setReport(buildReportInfo(jsonOrderDetailVo));
            //更改司机图像地址
            DriverVo driver = jsonOrderDetailVo.getDriver();
            if (driver != null && driver.getFace() != null) {
                jsonOrderDetailVo.setDriver(driver);
                //获取司机所有成功单数
                List<OrderDto> orderDtos = orderMapper.driverAccomplishOrder(driver.getUuid());
                if (orderDtos.size() != 0) {
                    driver.setOrderCount(orderDtos.size());
                }

            }
            //更改乘客图像地址
            PassengerVo passengerVo = jsonOrderDetailVo.getPassenger();
            if (passengerVo != null) {
                if (StringUtils.isNotEmpty(jsonOrderDetailVo.getActualPasNam())) {
                    passengerVo.setNickname(jsonOrderDetailVo.getActualPasNam());
                }
                if (StringUtils.isNotEmpty(jsonOrderDetailVo.getActualPasMob())) {
                    passengerVo.setMobile(jsonOrderDetailVo.getActualPasMob());
                }
                jsonOrderDetailVo.setPassenger(passengerVo);
            } else {
                PassengerVo passengerVoNew = new PassengerVo();
                passengerVoNew.setMobile(jsonOrderDetailVo.getActualPasMob());
                jsonOrderDetailVo.setPassenger(passengerVoNew);
            }
            //已完成订单计算实付金额
            if (jsonOrderDetailVo.getMainStatus().intValue() == ORDER_MAIN_STATUS_DONE) {
                //计算实付金额(已计算过调整费)
//                BigDecimal actualFare = BigDecimal.valueOf(jsonOrderDetailVo.getTotalFare()).setScale(1, BigDecimal.ROUND_HALF_UP);
                BigDecimal actualFares = jsonOrderDetailVo.getOrderFare().setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal actualFare = actualFares;
                //计算代理抽成和公司抽成后的金额
                //获取平台抽成比例
                SysBusinessOrganizationDto platform = sysBusinessOrganizationService.getPlatformCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (platform != null && platform.getCommission() != null && platform.getCommission() > 0) {
                    if (platform.getCommissionType() == 1) {//=1 按照百分比抽成
                        actualFare = actualFare.subtract(actualFares.multiply(BigDecimal.valueOf(platform.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        actualFare = actualFare.subtract(BigDecimal.valueOf(platform.getCommission()));
                    }
                }
                //获取代理抽成比例
                SysBusinessOrganizationDto agency = sysBusinessOrganizationService.getAgencyCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (agency != null && agency.getCommission() != null && agency.getCommission() > 0) {
                    if (agency.getCommissionType() == 1) {//=1 按照百分比抽成
                        actualFare = actualFare.subtract(actualFares.multiply(BigDecimal.valueOf(agency.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        actualFare = actualFare.subtract(BigDecimal.valueOf(agency.getCommission()));
                    }
                }
                //获取公司抽成比例
                SysBusinessOrganizationDto company = sysBusinessOrganizationService.getCompanyCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (company != null && company.getCommission() != null && company.getCommission() > 0) {
                    if (company.getCommissionType() == 1) {//=1 按照百分比抽成
                        actualFare = actualFare.subtract(actualFares.multiply(BigDecimal.valueOf(company.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        actualFare = actualFare.subtract(BigDecimal.valueOf(company.getCommission()));
                    }
                }
                jsonOrderDetailVo.setActualFare(BigDecimal.valueOf(jsonOrderDetailVo.getTotalFare()).subtract(jsonOrderDetailVo.getOrderFare()).add(actualFare).doubleValue());
                jsonOrderDetailVo.setTotalFare(BigDecimal.valueOf(jsonOrderDetailVo.getTotalFare()).subtract(jsonOrderDetailVo.getOrderFare()).add(actualFare).doubleValue());//这是计算佣金的时候添加的
                //获取支付时订单的优惠券价格，车费为0时不获取优惠券
                BigDecimal latestOrderFare = jsonOrderDetailVo.getLatestOrderFare() == null ? new BigDecimal(0) : jsonOrderDetailVo.getLatestOrderFare();
                if (!isOrderCanceled(jsonOrderDetailVo.getSubStatus()) && (latestOrderFare.compareTo(BigDecimal.ZERO) == 1)) {
                    ApiPasPayCouponParam couponParam = new ApiPasPayCouponParam();
                    couponParam.setUserUuid(jsonOrderDetailVo.getPassenger().getUuid());
                    couponParam.setBusinessType(jsonOrderDetailVo.getTypeModule());
                    couponParam.setTotalFare(jsonOrderDetailVo.getTotalFare());
                    couponParam.setOriginCityUuid(jsonOrderDetailVo.getOriginCityUuid());
                    PassengerCouponDto passengerCouponDto = passengerCouponService.findMinCoupon(couponParam).getData();
                    if (passengerCouponDto != null) {
                        jsonOrderDetailVo.setCouponUuid(passengerCouponDto.getUuid());
                        jsonOrderDetailVo.setCouponFare(passengerCouponDto.getMoney());
                        //计算优惠劵抵扣金额
//                        BigDecimal couponMoney = BigDecimal.valueOf(jsonOrderDetailVo.getCouponFare()).setScale(1, BigDecimal.ROUND_HALF_UP);
                        BigDecimal couponMoney = BigDecimal.valueOf(jsonOrderDetailVo.getCouponFare()).setScale(2, BigDecimal.ROUND_HALF_UP);
                        jsonOrderDetailVo.setCouponFare(couponMoney.compareTo(actualFare) == 1 ? actualFare.doubleValue() : passengerCouponDto.getMoney());
                        //计算实付
//                        actualFare = actualFare.subtract(BigDecimal.valueOf(jsonOrderDetailVo.getCouponFare())).setScale(1, BigDecimal.ROUND_HALF_UP);
                        actualFare = actualFare.subtract(BigDecimal.valueOf(jsonOrderDetailVo.getCouponFare())).setScale(2, BigDecimal.ROUND_HALF_UP);
                        jsonOrderDetailVo.setActualFare(actualFare.compareTo(BigDecimal.ZERO) == 1 ? actualFare.doubleValue() : 0D);
                    }
                }
            } else if(jsonOrderDetailVo.getMainStatus().intValue() == ORDER_MAIN_STATUS_PAYED){
                //支付完成的订单计算抽成后的金额
                BigDecimal orderFares = jsonOrderDetailVo.getOrderFare();
                BigDecimal orderFare = orderFares;
                //计算代理抽成和公司抽成后的金额
                //获取平台抽成比例
                SysBusinessOrganizationDto platform = sysBusinessOrganizationService.getPlatformCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (platform != null && platform.getCommission() != null && platform.getCommission() > 0) {
                    if (platform.getCommissionType() == 1) {//=1 按照百分比抽成
                        orderFare = orderFare.subtract(orderFares.multiply(BigDecimal.valueOf(platform.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        orderFare = orderFare.subtract(BigDecimal.valueOf(platform.getCommission()));
                    }
                }
                //获取代理抽成比例
                SysBusinessOrganizationDto agency = sysBusinessOrganizationService.getAgencyCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (agency != null && agency.getCommission() != null && agency.getCommission() > 0) {
                    if (agency.getCommissionType() == 1) {//=1 按照百分比抽成
                        orderFare = orderFare.subtract(orderFares.multiply(BigDecimal.valueOf(agency.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        orderFare = orderFare.subtract(BigDecimal.valueOf(agency.getCommission()));
                    }
                }
                //获取公司抽成比例
                SysBusinessOrganizationDto company = sysBusinessOrganizationService.getCompanyCommission(driverUuid, jsonOrderDetailVo.getTypeModule()).getData();
                if (company != null && company.getCommission() != null && company.getCommission() > 0) {
                    if (company.getCommissionType() == 1) {//=1 按照百分比抽成
                        orderFare = orderFare.subtract(orderFares.multiply(BigDecimal.valueOf(company.getCommission()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))).setScale(2, RoundingMode.HALF_UP);
                    } else if (platform.getCommissionType() == 2) {//=2 抽成固定金额
                        orderFare = orderFare.subtract(BigDecimal.valueOf(company.getCommission()));
                    }
                }
                jsonOrderDetailVo.setTotalFare((BigDecimal.valueOf(jsonOrderDetailVo.getTotalFare()).subtract(orderFares).add(orderFare)).doubleValue());
            }
            //跨城小件订单设置货件信息
            if (jsonOrderDetailVo.getTypeModule() == BUSINESS_TYPE_PARCEL && jsonOrderDetailVo.getParcelInfoName() != null) {
                String[] parcelInfoName = jsonOrderDetailVo.getParcelInfoName().split(",");
                jsonOrderDetailVo.setParcelTypeName(parcelInfoName[0]);
                jsonOrderDetailVo.setParcelWeightName(parcelInfoName[1]);
                jsonOrderDetailVo.setParcelVolumeName(parcelInfoName[2]);
                jsonOrderDetailVo.setParcelPhoto(jsonOrderDetailVo.getParcelPhoto());
            }
            if (jsonOrderDetailVo.getDriver() != null && jsonOrderDetailVo.getDriver().getPlateNum() == null) {
                jsonOrderDetailVo.getDriver().setPlateNum("");
            }
            if (jsonOrderDetailVo.getDriver() != null && jsonOrderDetailVo.getDriver().getCarColor() == null) {
                jsonOrderDetailVo.getDriver().setCarColor("");
            }
            if (jsonOrderDetailVo.getDriver() != null && jsonOrderDetailVo.getDriver().getBrandName() == null) {
                jsonOrderDetailVo.getDriver().setBrandName("");
            }
            if (null != jsonOrderDetailVo.getDriver()) {
                String valueTemp = AESUtils.decryptAES(jsonOrderDetailVo.getDriver().getName(), AESUtils.DEFAULT_KEY);
                if (StringUtils.isNotBlank(valueTemp)) {
                    jsonOrderDetailVo.getDriver().setName(valueTemp);
                }
            }
            String originAddressTemp = CommonUtils.getCounty(jsonOrderDetailVo.getOriginDetailAddress());
            if (StringUtils.isNotBlank(originAddressTemp)) {
                originAddressTemp = "（" + originAddressTemp + "）" + jsonOrderDetailVo.getOriginAddress();
                jsonOrderDetailVo.setOriginAddress(originAddressTemp);
            }
            String destAddressTemp = CommonUtils.getCounty(jsonOrderDetailVo.getDestDetailAddress());
            if (StringUtils.isNotBlank(destAddressTemp)) {
                destAddressTemp = "（" + destAddressTemp + "）" + jsonOrderDetailVo.getDestAddress();
                jsonOrderDetailVo.setDestAddress(destAddressTemp);
            }
            //跨城订单相关返回处理
            if (jsonOrderDetailVo.getTypeModule() == BUSINESS_TYPE_POOL || jsonOrderDetailVo.getTypeModule() == BUSINESS_TYPE_PARCEL) {
                //待支付状态时 支付获取优惠券
                if ((jsonOrderDetailVo.getJoinStatus() == ORDER_JOIN_STATUS_INIT || jsonOrderDetailVo.getJoinStatus() == ORDER_JOIN_STATUS_PASSENGER_PAY)
                        && jsonOrderDetailVo.getCloseStatus() == ORDER_CLOSE_STATUS_NORMAL) {
                    List<PassengerCouponDto> passengerCouponDtoList = passengerCouponService.findJoinMinCoupon(
                            jsonOrderDetailVo.getPassenger().getUuid(), jsonOrderDetailVo.getTypeModule(),
                            jsonOrderDetailVo.getTotalFare(), jsonOrderDetailVo.getOriginCityUuid()).getData();
                    if (passengerCouponDtoList != null && passengerCouponDtoList.size() > 0) {
                        PassengerCouponDto couponDto = passengerCouponDtoList.get(0);
                        jsonOrderDetailVo.setCouponUuid(couponDto.getUuid());
                        jsonOrderDetailVo.setCouponFare(couponDto.getMoney());
                    }
                }
                //订单处于已派单未完成状态时 返回当前激活订单与拼友信息
                if (jsonOrderDetailVo.getJoinStatus() >= ORDER_JOIN_STATUS_WAIT_START
                        && jsonOrderDetailVo.getJoinStatus() < ORDER_JOIN_STATUS_COMPLETED) {
                    Map<String, Object> paramMap = new HashMap<>();
                    paramMap.put("mainOrderUuid", jsonOrderDetailVo.getMainOrderUuid());
                    List<AllPassengerOrderVo> otherOrderInfoList = orderMapper.allPassengerOrderInfo(MapUtils.build("mainOrderUuid", jsonOrderDetailVo.getMainOrderUuid()));
                    //取出当前订单 并处理当前激活订单
                    if (otherOrderInfoList != null && otherOrderInfoList.size() > 0) {
                        //当前激活订单
                        for (AllPassengerOrderVo orderVo : otherOrderInfoList) {
                            //顺位第一个待接驾、待上车订单或者行程中订单为激活订单
                            if (orderVo.getJoinStatus() == ORDER_JOIN_STATUS_DRIVER_DEPARTURE
                                    || orderVo.getJoinStatus() == ORDER_JOIN_STATUS_STARTED
                                    || orderVo.getJoinStatus() == ORDER_JOIN_STATUS_ARRIVE_POINT) {
                                jsonOrderDetailVo.setActivateOrderUuid(orderVo.getOrderUuid());
                                jsonOrderDetailVo.setActivatePassengerName(orderVo.getPassengerName());
                                jsonOrderDetailVo.setActivateOrderModule(orderVo.getTypeModule());
                                break;
                            }
                        }
                        jsonOrderDetailVo.setAllPassengerOrderInfo(otherOrderInfoList);
                    }
                } else if (jsonOrderDetailVo.getJoinStatus() > ORDER_JOIN_STATUS_STARTED) {
                    //跨城订单已完成时 加载定位点
                    jsonOrderDetailVo.setTracePoints(getCrosstownTracePoint(jsonOrderDetailVo));
                }
            } else {
                //非跨城加载订单详情位置点
                log.info("----加载订单:{}详情位置点begin----", uuid);
                jsonOrderDetailVo.setTracePoints(getTracePoint(uuid, jsonOrderDetailVo.getActualDriverUuid(),
                        jsonOrderDetailVo.getAppid(), jsonOrderDetailVo.getMainStatus()));
                log.info("----加载订单:{}详情位置点end----", jsonOrderDetailVo);
            }
            return ResponseData.buildSuccessResponse("获取成功", jsonOrderDetailVo);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查无数据");
    }

    /**
     * 获取订单详情位置点
     *
     * @param orderUuid
     * @param driverUuid
     * @param appid
     * @return
     */
    private String getTracePoint(String orderUuid, String driverUuid, String appid, int mainStatus) {
        String orderDetailPoints = "order_detail_points" + orderUuid;
        //先取缓存，有直接返回
        Object resultObj = redisCacheService.get(orderDetailPoints);
        if (resultObj != null) {
            log.info("订单id:{}, 缓存获取定位点集合成功，resultStr={}", orderUuid, resultObj);
            return (String) resultObj;
        }
        //获取乘客上车到乘客到达目的地过程中的所有点
        ResponseData<List<DriverLocation>> responseData = locationService.findOrderMapPoint(orderUuid, appid);
        if (responseData == null || CollectionUtils.isEmpty(responseData.getData())) {
            log.info("------------------订单id:{} mongo中未获取到点", orderUuid);
            return null;
        }
        List<LatLngDto> mongoPoints = new ArrayList<>();
        for (DriverLocation driverLocation : responseData.getData()) {
            //订单状态300表示乘客上车、行程开始，乘车上车到乘客下车
            if (driverLocation.getOrderStatus() != null && (ORDER_STATUS_START.equals(driverLocation
                    .getOrderStatus()) || ORDER_STATUS_ARRIVED.equals(driverLocation.getOrderStatus()))) {
                LatLngDto latLng = new LatLngDto();
                latLng.setLatitude(driverLocation.getCoordinate().getLat());
                latLng.setLongitude(driverLocation.getCoordinate().getLng());
                mongoPoints.add(latLng);
            }
        }
        //查看服务端配置项 是否开启纠偏
        List<LatLngDto> checkTraceList = new ArrayList<>();
        if (ApplicationConfig.SERVER_CONFIG.getSystem().getTurnOnCorrection()) {
            ResponseData<List<TrackVo>> listResponseData = distanceService.gaodeTraceCheck(driverUuid, orderUuid, new TrsearchParam());
            if (listResponseData.isSuccess() && CollectionUtils.isNotEmpty(listResponseData.getData())) {
                TrackVo trackVo = listResponseData.getData().get(0);
                checkTraceList = trackVo.getPoints().stream().map(point -> {
                    String location = point.getLocation();
                    String[] split = location.split(",");
                    LatLngDto latLng = new LatLngDto();
                    latLng.setLongitude(Double.parseDouble(split[0]));
                    latLng.setLatitude(Double.parseDouble(split[1]));
                    return latLng;
                }).collect(Collectors.toList());
                log.info("------------------订单id:{} 进行鹰眼轨迹纠偏成功,定位点个数：{}", orderUuid, checkTraceList.size());
            }
        }
        if (CollectionUtils.isNotEmpty(checkTraceList)) {
            resultObj = PolylineUtils.encodePoly(checkTraceList);
        } else {
            resultObj = PolylineUtils.encodePoly(mongoPoints);
        }
        log.info("--返回压缩后结果resultStr = {}", resultObj);
        //订单状态为3：订单结束（待支付）4：支付完成的加入缓存，保存7天
        if (resultObj != null && (mainStatus == ORDER_MAIN_STATUS_DONE || mainStatus == ORDER_MAIN_STATUS_PAYED)) {
            redisCacheService.set(orderDetailPoints, resultObj, 24 * 60L);
        }
        return (String) resultObj;
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> queryOrderDone(ApiOrderListParam orderListParam) {
        PageBounds pageBounds = new PageBounds(orderListParam.getNowPage(), orderListParam.getPageSize());
        Map<String, Object> paramMap = MapUtils.build(4);
        paramMap.put("passengerUuid", orderListParam.getUserUuid());
        if (StringUtils.isNotEmpty(orderListParam.getBusinessTypes())) {
            paramMap.put("businessTypes", org.springframework.util.StringUtils.commaDelimitedListToSet(orderListParam.getBusinessTypes()));
        }
        return ResponseData.buildSuccessResponse(orderMapper.queryOrderDone(paramMap, pageBounds));
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> queryOrderDoing(ApiOrderListParam orderListParam) {
        Map<String, Object> paramMap = MapUtils.build(1);
        paramMap.put("passengerUuid", orderListParam.getUserUuid());
        if (StringUtils.isNotEmpty(orderListParam.getBusinessTypes())) {
            paramMap.put("businessTypes", org.springframework.util.StringUtils.commaDelimitedListToSet(orderListParam.getBusinessTypes()));
        }
        return ResponseData.buildSuccessResponse(orderMapper.queryOrderDoing(paramMap));
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> queryOrderDriDoing(ApiOrderListParam orderListParam) {
        Map<String, Object> paramMap = MapUtils.build(1);
        paramMap.put("actualDriverUuid", orderListParam.getUserUuid());
        if (StringUtils.isNotEmpty(orderListParam.getBusinessTypes())) {
            paramMap.put("businessTypes", org.springframework.util.StringUtils.commaDelimitedListToSet(orderListParam.getBusinessTypes()));
        }
        return ResponseData.buildSuccessResponse(orderMapper.queryOrderDoing(paramMap));
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> queryBillOrder(ApiPageParam apiPageParam) {
        Map<String, Object> paramMap = MapUtils.build(4);
        paramMap.put("passengerUuid", apiPageParam.getUserUuid());
        paramMap.put("canBill", MagicConstant.INT_ONE);
        return ResponseData.buildSuccessResponse(orderMapper.queryOrderDone(paramMap, new PageBounds(
                apiPageParam.getNowPage(), apiPageParam.getPageSize())));
    }

    @Override
    public ResponseData<Boolean> updPickUpPas(String orderUuid, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败,找不到该订单");
        }
        if (ORDER_STATUS_CONFIRM.equals(orderDto.getSubStatus()) && ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            updateOrderStatus(orderDto, ORDER_STATUS_GO, null);
            //更新yy_order_fare
            OrderFareDto fareParam = new OrderFareDto();
            fareParam.setDriDepartTime(new Date());
            fareParam.setOrderUuid(orderUuid);
            ResponseData<OrderFareDto> findByOrderUuid = orderFareService.findByOrderUuid(orderUuid);
            if (findByOrderUuid.isSuccess() && findByOrderUuid.getData() != null) {
                fareParam.setUuid(findByOrderUuid.getData().getUuid());
            }
            orderFareService.saveOrUpdate(fareParam);
            //推送给乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "司机已接单",
                    "司机正赶来接驾，请耐心等候", ORDER_DRIVER_SET_OUT, MapUtils.build("typeModule", orderDto.getTypeModule()));
            //上传点
            uploadTextResult(uploadText);
            // 因为与主逻辑无关 所以异步统计里程
            ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                    driverStatusCycleService,
                    locationService,
                    orderDto.getAppid(),
                    orderDto.getActualDriverUuid(), orderUuid,
                    orderDto.getCarUuid(),
                    // 空驶
                    DriverStatusCycleDto.ACTION_LEAVE));
            //根据orderUuid查询该订单，没有返回null
            OrderDetailDto orderDetailDto = findOrderDetail(orderUuid);
            if (null == orderDetailDto) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单详情");
            }
            DriverDto driverDto = driverService.get(orderDto.getActualDriverUuid()).getData();
            if (driverDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机数据");
            } else {
                //拿到司机信息查看是否出车、
                DriverDto driverDto1 = driverService.findWorkedDrivers(driverDto.getCarUuid()).getData().get(0);
                if (!driverDto1.getUuid().equals(driverDto.getUuid())) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "同车的其它司机已出车");
                }
            }
            CarDto carDto = carService.get(driverDto.getCarUuid()).getData();
            if (carDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到车辆信息");
            }
            // 紧急联系人行程分享
            passengerEmergencyPush(orderDto, orderDetailDto, driverDto, carDto);
            return ResponseData.buildSuccessResponse("修改状态成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(
                GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());
    }

    @Override
    public ResponseData<Boolean> updDepart(String orderUuid, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());
        }
        if (!ORDER_STATUS_GO.equals(orderDto.getSubStatus()) && !ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败,找不到该订单");
        }
        updateOrderStatus(orderDto, ORDER_STATUS_ARRIVE, null);
        OrderFareDto orderFareDto = orderFareService.get(MapUtils.build("orderUuid", orderUuid)).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
        }
        OrderFareDto updOrderFareDto = new OrderFareDto();
        updOrderFareDto.setDriArrTime(new Date());
        updOrderFareDto.setUuid(orderFareDto.getUuid());
        orderFareService.saveOrUpdate(updOrderFareDto);
        //推送给乘客
        pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "司机到达上车地点",
                "司机已到达上车地点，请及时上车", ORDER_DRIVER_ARRIVE_PICK_UP_LOCATION);
        uploadTextResult(uploadText);
        return ResponseData.buildSuccessResponse("修改状态成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> updGeton(String orderUuid, Double waitMile, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());
        }
        if (ORDER_STATUS_ARRIVE.equals(orderDto.getSubStatus()) && ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            updateOrderStatus(orderDto, ORDER_STATUS_START, null);
            ResponseData<Map<String, Object>> result = getWaitFareAndTime(orderDto);
            if (!result.isSuccess()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取超时等待信息错误");
            }
            Map<String, Object> resultMap = result.getData();
            //更新订单价格详情记录
            OrderFareDto updOrderFareDto = new OrderFareDto();
            updOrderFareDto.setWaitFare((Double) resultMap.get("waitFare"));
            updOrderFareDto.setWaitDuration((Integer) resultMap.get("waitTime"));
            updOrderFareDto.setStartTrip((Double) resultMap.get("startTrip"));
            updOrderFareDto.setStartDuration((Integer) resultMap.get("startDuration"));
            updOrderFareDto.setStartFare((Double) resultMap.get("startFare"));
            updOrderFareDto.setPasArrTime(new Date());
            updOrderFareDto.setUuid(String.valueOf(resultMap.get("orderFareUuid")));
            updOrderFareDto.setUpdateOn(new Date());
            updOrderFareDto.setWaitTimeSeconds((Integer) resultMap.get("waitTimeAmountSeconds"));
            updOrderFareDto.setWaitMile(waitMile);
            orderFareService.saveOrUpdate(updOrderFareDto);
            //保存点
            if (StringUtils.isNotEmpty(uploadText)) {
                boolean uploadResult = uploadTextResult(uploadText);
                if (!uploadResult) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存定位点失败");
                }
            }
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "行程开始", "行程开始",
                    ORDER_DRIVER_START_SERVICE);
            // 因为与主逻辑无关 所以异步统计里程
            ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                    driverStatusCycleService,
                    locationService,
                    orderDto.getAppid(),
                    orderDto.getActualDriverUuid(), orderUuid,
                    orderDto.getCarUuid(),
                    // 空载
                    DriverStatusCycleDto.ACTION_RIDE));
            return ResponseData.buildSuccessResponse("修改状态成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败，找不到该订单");
    }


    /**
     * 获取超时等待时间与金额
     */
    private ResponseData<Map<String, Object>> getWaitFareAndTime(OrderDto orderDto) {
        //获取超时等待时间 与 超时等待费用
        CarModelValuationDto carValuationDto = orderFareService.getCarModelValuationDto(orderDto.getUuid()).getData();
        if (null == carValuationDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败，找不到指定车辆计费规则");
        }
        OrderFareDto orderFareDto = orderFareService.get(MapUtils.build("orderUuid", orderDto.getUuid())).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单价格详情失败");
        }
        if (orderFareDto.getDriArrTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机到达上车地点时间");
        }

        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderDto.getUuid())).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单附加详情失败");
        }
        if (orderDetailDto.getDeparTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机出发时间");
        }

        //获取司机到达上车地点时间
        long driverArriveTime = orderFareDto.getDriArrTime().getTime();
        //获取出发时间
        long departTime = orderDetailDto.getDeparTime().getTime();
        //免费等待时长(分钟)
        int freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime();
        //获取等待的分钟数(如果司机提早到达，则以出发时间开始算起，如果司机迟到，则以司机到达的时间开始算)
        int waitTime;
        int waitTimeAmountSeconds;
        Date date = new Date();
        //乘客在预约时间之后上车
        if (driverArriveTime <= departTime && date.getTime() > departTime) {
            waitTime = (int) Math.ceil((date.getTime() - departTime) / (60 * 1000d));
            waitTimeAmountSeconds = (int) Math.ceil((date.getTime() - departTime) / 1000d);
        } else {
            waitTime = (int) Math.ceil((date.getTime() - driverArriveTime) / (60 * 1000d));
            waitTimeAmountSeconds = (int) Math.ceil((date.getTime() - driverArriveTime) / 1000d);
        }
        int beyondWaitTime = 0;
        double beyondWaitFare = 0.0;
        //如果超时等待时间大于免费等待的时间
        if (waitTime > freeWaitTime) {
            beyondWaitTime = waitTime - freeWaitTime;
            double waitFareDefined = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
            //四舍五入保留一位小数
//            beyondWaitFare = BigDecimal.valueOf(waitFareDefined * beyondWaitTime).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
            beyondWaitFare = BigDecimal.valueOf(waitFareDefined * beyondWaitTime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        Map<String, Object> buildParam = MapUtils.build();
        //这边取的是等待乘客总时间
        buildParam.put("waitTimeAmountSeconds", waitTimeAmountSeconds);
        //这边取的是扣掉免费等待市场的时间
        buildParam.put("waitTime", beyondWaitTime);
        buildParam.put("waitFare", beyondWaitFare);
        buildParam.put("startTrip", carValuationDto.getStartTrip());
        buildParam.put("startDuration", carValuationDto.getStartDuration());
        buildParam.put("startFare", carValuationDto.getStartFare());
        buildParam.put("orderFareUuid", orderFareDto.getUuid());
        return ResponseData.buildSuccessResponse("获取成功", buildParam);
    }

    @Override
    public ResponseData<Boolean> taxiUpdArrive(String orderUuid, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null != orderDto) {
            if (ORDER_STATUS_START.equals(orderDto.getSubStatus())
                    && ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
                Map<String, Object> fareMap = MapUtils.build(1);
                fareMap.put("orderUuid", orderUuid);
                OrderFareDto orderFareDto = orderFareService.get(fareMap).getData();
                if (orderFareDto == null) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
                }
                OrderFareDto updOrderFareDto = new OrderFareDto();
                updOrderFareDto.setUuid(orderFareDto.getUuid());
                //设置乘客到达目的地时间
                updOrderFareDto.setArriveTime(new Date());
                updOrderFareDto.setUpdateOn(new Date());
                //实际行驶时长（毫秒/(1000*60)=分钟）
                Long tripDuration = ((new Date()).getTime() - orderFareDto.getPasArrTime().getTime()) / (1000 * 60);
                //设置实际行驶时长
                updOrderFareDto.setTripDuration(Integer.valueOf(tripDuration.toString()));

                double actualFare = orderFareDto.getActualFare() == null ? 0 : orderFareDto.getActualFare().doubleValue();
                //设置总金额
                updOrderFareDto.setTotalFare(actualFare);
                //设置实际行驶费用
//                updOrderFareDto.setOrderFare(BigDecimal.valueOf(updOrderFareDto.getTotalFare()).setScale(1, BigDecimal.ROUND_HALF_UP));
                updOrderFareDto.setOrderFare(BigDecimal.valueOf(updOrderFareDto.getTotalFare()).setScale(2, BigDecimal.ROUND_HALF_UP));
                orderFareService.saveOrUpdate(updOrderFareDto);
                //上传上车点
                boolean isSuccess = uploadTextResult(uploadText);
                if (!isSuccess) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "上传定位点失败，请重试");
                }
                //更新订单状态
                updateOrderStatus(orderDto, ORDER_STATUS_ARRIVED, null);
                //推送给乘客
                pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "保存成功", "保存金额成功",
                        ORDER_DRIVER_CONFIRM_FARE);
                // 因为与主逻辑无关 所以异步统计里程
                ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                        driverStatusCycleService,
                        locationService,
                        orderDto.getAppid(),
                        orderDto.getActualDriverUuid(), orderUuid,
                        orderDto.getCarUuid(),
                        // 服务
                        DriverStatusCycleDto.ACTION_SERVICE_OVER));

                return ResponseData.buildSuccessResponse("更改订单状态成功", Boolean.TRUE);
            }
            //上传上车点
            boolean isSuccess = uploadTextResult(uploadText);
            if (!isSuccess) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "上传定位点失败，请重试");
            }
            //推送给乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "达到目的地", "到达目的地，请及时支付车费",
                    ORDER_DRIVER_ARRIVE_DESTINATION);
            // 因为与主逻辑无关 所以异步统计里程
            ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                    driverStatusCycleService,
                    locationService,
                    orderDto.getAppid(),
                    orderDto.getActualDriverUuid(), orderUuid,
                    orderDto.getCarUuid(),
                    // 服务
                    DriverStatusCycleDto.ACTION_SERVICE_OVER));
            return ResponseData.buildSuccessResponse("修改状态成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());
    }

    @Override
    public ResponseData<Map<String, Object>> getOrderStatus(String uuid, Integer typeModule) {
        //取等待叫车的订单
        ResponseData<Map<String, Object>> waitingOrderList = getWaitingOrder(uuid, typeModule);
        if (waitingOrderList.isSuccess()) {
            return waitingOrderList;
        }
        //取有预约的订单
        ResponseData<Map<String, Object>> reservationOrderList = getReservationOrder(uuid, typeModule, CommonConstant.PASSENGER);
        if (reservationOrderList.isSuccess()) {
            return reservationOrderList;
        }
        //取有进行中的订单
        ResponseData<Map<String, Object>> doingList = getOrderOfDoing(uuid, typeModule, CommonConstant.PASSENGER);
        if (doingList.isSuccess()) {
            return doingList;
        }
        //取有未支付的订单
        ResponseData<Map<String, Object>> waitingPayOrderList = getWaitingPayOrder(uuid, typeModule, CommonConstant.PASSENGER);
        if (waitingPayOrderList.isSuccess()) {
            return waitingPayOrderList;
        }
        Map<String, Object> map = MapUtils.build();
        map.put("status", HOMEPAGE_ORDER_STATUS_NULL);
        return ResponseData.buildSuccessResponse("无待处理订单", map);
    }

    @Override
    public ResponseData<Map<String, Object>> getDriOrderStatus(String uuid, Integer typeModule) {
        //1、有订单（预约单）已超过出发时间（等待接驾未出发）
        ResponseData<Map<String, Object>> reservationOrderAfterList = getReservationOrderAfter(uuid, typeModule, CommonConstant.DRIVER);
        if (reservationOrderAfterList.isSuccess()) {
            return reservationOrderAfterList;
        }
        //2、有订单正在进行中，已出发，未确认金额
        ResponseData<Map<String, Object>> doingList = getOrderOfDoing(uuid, typeModule, CommonConstant.DRIVER);
        if (doingList.isSuccess()) {
            return doingList;
        }
        //3、有订单长时间未支付（金额确认后超过1小时未支付）
        //取有未支付的订单
        // AjaxList waitingPayOrderList = getWaitingPayOrder(uuid, orderTypeTripTaxi,CommonConstant.DRIVER);
        //if (waitingPayOrderList.isSuccess()) {
        //   return waitingPayOrderList;
        // }
        //4、有订单（预约单）即将开始（10分钟内）
        ResponseData<Map<String, Object>> reservationOrderList = getReservationOrder(uuid, typeModule, CommonConstant.DRIVER);
        if (reservationOrderList.isSuccess()) {
            return reservationOrderList;
        }
        Map<String, Object> map = MapUtils.build();
        map.put("status", HOMEPAGE_ORDER_STATUS_NULL);
        return ResponseData.buildSuccessResponse("无待处理订单", map);
    }

    /**
     * @param userUuid   用户的编号
     * @param typeModule 订单类型
     * @return
     */
    private ResponseData<Map<String, Object>> getWaitingOrder(String userUuid, Integer typeModule) {
        Map<String, Object> orderMap = MapUtils.build();
        orderMap.put("passengerUuid", userUuid);
        orderMap.put("typeModule", typeModule);
        orderMap.put("subStatus", ORDER_STATUS_WAIT);
        orderMap.put("mainStatus", ORDER_MAIN_STATUS_INITIAL);
        //在查询等待应答的订单之前 查看是否有超过五分钟的订单，超过五分钟的订单状态设置为已取消
        List<OrderDto> orderOverTimeList = this.orderMapper.list(orderMap);
        if (orderOverTimeList.size() > 0) {
            Date nowDate = new Date();
            for (OrderDto orderDto : orderOverTimeList) {
                if ((nowDate.getTime() - orderDto.getCreateOn().getTime()) / 1000 > 300) {
                    orderDto.setMainStatus(ORDER_MAIN_STATUS_CANCEL);
                    orderDto.setSubStatus(ORDER_STATUS_NO_ANSWER);
                    orderDto.setUpdateOn(new Date());
                    this.orderMapper.edit(orderDto);
                }
            }
        }
        List<JsonOrderListVo> orderList = orderMapper.getAllByStatus(orderMap);
        Map<String, Object> map = MapUtils.build();
        if (orderList != null && orderList.size() > 0) {
            JsonOrderListVo jsonOrder = orderList.get(0);
            //有等待应答的订单
            map.put("status", Constants.HOMEPAGE_ORDER_STATUS_WAIT);
            map.put("typeModule", jsonOrder.getTypeModule());
            map.put("orderUuid", jsonOrder.getUuid());
            map.put("mainStatus", jsonOrder.getMainStatus());
            map.put("subStatus", jsonOrder.getSubStatus());
            return ResponseData.buildSuccessResponse("有等待应答的订单", map);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无等待应答的订单");
    }

    /**
     * @param userUuid   用户的编号
     * @param typeModule 订单类型
     * @param userType   用户类型  1：乘客  2：司机
     * @return
     */
    private ResponseData<Map<String, Object>> getOrderOfDoing(String userUuid, Integer typeModule, Integer userType) {
        Map<String, Object> orderMap = MapUtils.build(4);
        orderMap.put("typeModule", typeModule);
        if (CommonConstant.DRIVER == userType) {
            orderMap.put("actualDriverUuid", userUuid);
            //doing非空的时候，获取即时订单或者当前时间小于预约时间的预约单
            orderMap.put("doing", 1);
        }
        if (CommonConstant.PASSENGER == userType) {
            orderMap.put("passengerUuid", userUuid);
            //正在进行中的订单只过滤司机已经出发后的状态
            orderMap.put("isGoOn", 1);
        }
        if (typeModule != null && (BUSINESS_TYPE_POOL == typeModule || BUSINESS_TYPE_PARCEL == typeModule)) {
            orderMap.put("joinStatusList", Arrays.asList(ORDER_JOIN_STATUS_WAIT_START, ORDER_JOIN_STATUS_DRIVER_DEPARTURE,
                    ORDER_JOIN_STATUS_ARRIVE_POINT, ORDER_JOIN_STATUS_PASSENGER_ABOARD, ORDER_JOIN_STATUS_STARTED));
        } else {
            orderMap.put("mainStatus", Constants.HOMEPAGE_ORDER_STATUS_DOING);
        }
        List<JsonOrderListVo> orderList = orderMapper.getAllByStatus(orderMap);
        Map<String, Object> map = MapUtils.build(8);
        if (CollectionUtils.isNotEmpty(orderList)) {
            JsonOrderListVo jsonOrder = orderList.get(0);
            //有进行中的订单
            map.put("status", Constants.HOMEPAGE_ORDER_STATUS_DOING);
            map.put("typeModule", jsonOrder.getTypeModule());
            map.put("orderUuid", jsonOrder.getUuid());
            map.put("mainStatus", jsonOrder.getMainStatus());
            map.put("subStatus", jsonOrder.getSubStatus());
            map.put("joinStatus", jsonOrder.getJoinStatus());
            return ResponseData.buildSuccessResponse("您有订单仍在进行中", map);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无进行中的订单");
    }


    /**
     * @param userUuid   用户的编号
     * @param typeModule
     * @return AjaxList
     */
    private ResponseData<Map<String, Object>> getWaitingPayOrder(String userUuid, Integer typeModule, Integer userType) {
        Map<String, Object> nopayMap = MapUtils.build(8);
        nopayMap.put("typeModule", typeModule);
        if (CommonConstant.DRIVER == userType) {
            nopayMap.put("actualDriverUuid", userUuid);
        }
        if (CommonConstant.PASSENGER == userType) {
            nopayMap.put("passengerUuid", userUuid);
        }
        if (typeModule != null && (BUSINESS_TYPE_POOL == typeModule || BUSINESS_TYPE_PARCEL == typeModule)) {
            nopayMap.put("joinStatusList", Arrays.asList(ORDER_JOIN_STATUS_INIT, ORDER_JOIN_STATUS_PASSENGER_PAY));
        } else {
            nopayMap.put("mainStatus", ORDER_MAIN_STATUS_DONE);
        }
        List<JsonOrderListVo> nopayList = orderMapper.getAllByStatus(nopayMap);
        Map<String, Object> map = MapUtils.build();
        if (CollectionUtils.isNotEmpty(nopayList)) {
            JsonOrderListVo jsonOrder = nopayList.get(0);
            map.put("status", Constants.HOMEPAGE_ORDER_STATUS_WAIT_PAY);
            map.put("typeModule", jsonOrder.getTypeModule());
            map.put("orderUuid", jsonOrder.getUuid());
            map.put("mainStatus", jsonOrder.getMainStatus());
            map.put("subStatus", jsonOrder.getSubStatus());
            map.put("joinStatus", jsonOrder.getJoinStatus());
            //对于司机，超过1小时未支付的订单才提示
            Date updateTime = jsonOrder.getUpdateOn() == null ? new Date() : jsonOrder.getUpdateOn();
            if (CommonConstant.DRIVER == userType && DateUtils.compareByMins(updateTime, new Date(), 60)) {
                return ResponseData.buildSuccessResponse("您有订单已等待支付较久，可联系乘客尽快支付", map);
            }
            if (CommonConstant.PASSENGER == userType) {
                return ResponseData.buildSuccessResponse("有未支付的订单", map);
            }
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无待支付的订单");
    }

    /**
     * @param userUuid   用户的编号
     * @param typeModule 订单类型
     * @param userType   用户类型  1：乘客  2：司机  @return AjaxList
     * @return
     */
    private ResponseData<Map<String, Object>> getReservationOrder(String userUuid, Integer typeModule, Integer userType) {
        Map<String, Object> orderMap = MapUtils.build(4);
        orderMap.put("typeModule", typeModule);
        if (CommonConstant.DRIVER == userType) {
            orderMap.put("actualDriverUuid", userUuid);
        }
        if (CommonConstant.PASSENGER == userType) {
            orderMap.put("passengerUuid", userUuid);
        }
        if (typeModule != null && (BUSINESS_TYPE_POOL == typeModule || BUSINESS_TYPE_PARCEL == typeModule)) {
            orderMap.put("joinStatusList", Arrays.asList(ORDER_JOIN_STATUS_SUB_OK));
        } else {
            orderMap.put("mainStatus", ORDER_MAIN_STATUS_DOING);
            orderMap.put("subStatus", ORDER_STATUS_CONFIRM);
        }
        List<JsonOrderListVo> orderList = orderMapper.getAllByStatus(orderMap);
        if (orderList != null && orderList.size() > 0) {
            for (JsonOrderListVo jsonOrder : orderList) {
                Date departTime = jsonOrder.getDeparTime() == null ? new Date() : jsonOrder.getDeparTime();
                Map<String, Object> map = MapUtils.build();
                map.put("typeModule", jsonOrder.getTypeModule());
                map.put("orderUuid", jsonOrder.getUuid());
                map.put("mainStatus", jsonOrder.getMainStatus());
                map.put("subStatus", jsonOrder.getSubStatus());
                map.put("joinStatus", jsonOrder.getJoinStatus());
                if (!DateUtils.compareByMins(new Date(), departTime, 10)) {
                    //有预约的订单
                    map.put("status", Constants.HOMEPAGE_ORDER_STATUS_APPOINT);
                    return ResponseData.buildSuccessResponse("有预约的即将出发的订单", map);
                } else if (System.currentTimeMillis() > departTime.getTime()) {
                    //有预约的订单
                    map.put("status", Constants.HOMEPAGE_ORDER_STATUS_APPOINT_AFTER1);
                    return ResponseData.buildSuccessResponse("有超过预约时间的订单", map);
                }
            }
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无预约的订单");
    }

    /**
     * 获取超过出发时间了的预约单
     *
     * @param userUuid
     * @param typeModule
     * @param userType
     * @return
     */
    private ResponseData<Map<String, Object>> getReservationOrderAfter(String userUuid, Integer typeModule, Integer userType) {
        Map<String, Object> orderMap = MapUtils.build(5);
        if (CommonConstant.DRIVER == userType) {
            orderMap.put("actualDriverUuid", userUuid);
        } else if (CommonConstant.PASSENGER == userType) {
            orderMap.put("passengerUuid", userUuid);
        }
        orderMap.put("mainStatus", ORDER_MAIN_STATUS_DOING);
        orderMap.put("subStatus", ORDER_STATUS_CONFIRM);
        orderMap.put("typeModule", typeModule);
        //afterPoint为1，就查询超过出发时间的单
        orderMap.put("afterPoint", 1);

        List<JsonOrderListVo> orderList = orderMapper.getAllByStatus(orderMap);
        Map<String, Object> map = MapUtils.build();
        if (orderList != null && orderList.size() > 0) {
            JsonOrderListVo jsonOrder = orderList.get(0);
            //有预约的订单
            map.put("status", Constants.HOMEPAGE_ORDER_STATUS_APPOINT_AFTER);
            map.put("typeModule", jsonOrder.getTypeModule());
            map.put("orderUuid", jsonOrder.getUuid());
            map.put("mainStatus", jsonOrder.getMainStatus());
            map.put("subStatus", jsonOrder.getSubStatus());
            return ResponseData.buildSuccessResponse("有超过出发时间的预约订单", map);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无预约的订单");
    }

    @Override
    public ResponseData<Boolean> noConfirmCancel(ApiOrderNoAnswerCancelParam cancelParam) {
        OrderDto orderDto = findOrder(cancelParam.getOrderUuid());
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未检索到订单");
        }
        if (!ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus()) && !ORDER_STATUS_WAIT.equals(orderDto.getSubStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，订单状态异常");
        }
        int subStatus = cancelParam.getType() == 1 ? ORDER_STATUS_PASSENGER_CANCEL : ORDER_STATUS_NO_ANSWER;
        //更新订单主表
        updateOrderStatus(orderDto, subStatus, ORDER_MAIN_STATUS_CANCEL);
        //更新订单明细表
        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderDto.getUuid())).getData();
        if (orderDetailDto != null) {
            OrderDetailDto updateOrderDetailDto = new OrderDetailDto();
            updateOrderDetailDto.setUuid(orderDetailDto.getUuid());
            updateOrderDetailDto.setCancelTime(new Date());
            updateOrderDetailDto.setCancelReason(cancelParam.getType() == 1 ? "未确定行程乘客取消订单" : "未确定行程系统自动取消订单");
            orderDetailService.edit(updateOrderDetailDto);
        }
        //给其余司机推送消息
        Object object = redisCacheService.get("push" + cancelParam.getOrderUuid());
        if (object != null) {
            pushListOrder2Pas((List<String>) object, orderDto.getUuid(), orderDto.getAppid(), null,
                    cancelParam.getType() == 1 ? "订单已被乘客取消" : "订单已自动取消",
                    cancelParam.getType() == 1 ? ORDER_PASSENGER_CANCEL : ORDER_OVER_TIME_CANCEL, MapUtils.build("hasDriver", false));
        }
        //解绑隐私号
        orderSecretNoService.unbind(cancelParam.getOrderUuid());
        return ResponseData.buildSuccessResponse("取消订单成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> pasConfirmCancel(String orderUuid, String cancelMsg) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未检索到订单");
        }
        CarModelValuationDto carValuationDto = orderFareService.getCarModelValuationDto(orderDto.getUuid()).getData();
        if (carValuationDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未检索到车辆信息");
        }
        if (orderDto.getMainStatus() == null || orderDto.getSubStatus() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，订单状态异常");
        }
        if (ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，初始化的订单不能取消");
        }
        if (ORDER_MAIN_STATUS_DONE.equals(orderDto.getMainStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，待支付的订单不能取消");
        }
        if (ORDER_MAIN_STATUS_CANCEL.equals(orderDto.getMainStatus())) {
            return ResponseData.buildSuccessResponse("取消订单成功", Boolean.TRUE);
        }
        if (ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            //行程确定 到 行程开始之前 乘客可以取消订单
            boolean success = false;
            if (orderDto.getSubStatus().equals(ORDER_STATUS_CONFIRM)) {
                updateOrderStatus(orderDto, ORDER_STATUS_PASS_CANCEL_CONFIRM_FREE, ORDER_MAIN_STATUS_CANCEL);
                success = true;
            } else if (orderDto.getSubStatus().equals(ORDER_STATUS_GO)) {
                updateOrderStatus(orderDto, ORDER_STATUS_PASS_CANCEL_GO_FREE, ORDER_MAIN_STATUS_CANCEL);
                success = true;
            } else if (orderDto.getSubStatus().equals(ORDER_STATUS_ARRIVE)) {
                //插入取消产生的费用到价格表
                ResponseData<Void> orderFare4PasCancel = updOrderFare4PasCancel(orderDto, carValuationDto);
                if (!orderFare4PasCancel.isSuccess()) {
                    return ResponseData.buildErrorResponse(orderFare4PasCancel.getErrCode(), orderFare4PasCancel.getMsg());
                }
                success = true;
            }
            if (success) {
                //插入取消原因到订单详情表
                ResponseData<Void> orderDetail4PasCancel = updOrderDetail4PasCancel(orderUuid, cancelMsg);
                if (!orderDetail4PasCancel.isSuccess()) {
                    return ResponseData.buildErrorResponse(orderDetail4PasCancel.getErrCode(), orderDetail4PasCancel.getMsg());
                }
                //推送给司机，已取消订单
                pushOrder2Dri(orderDto.getActualDriverUuid(), orderDto.getUuid(), orderDto.getAppid(), "行程已取消",
                        "乘客已取消订单", ORDER_PASSENGER_CANCEL, MapUtils.build("typeModule", orderDto.getTypeModule()));
                //检索乘客信息
                PassengerDto passenger = passengerService.get(orderDto.getPassengerUuid()).getData();
                //检索司机信息
                DriverVo actDriver = driverService.commonSelInfo(MapUtils.build("uuid", orderDto.getActualDriverUuid())).getData();
                //发送短信给司机（长连接通道不存在的时候）
                if (!pushService.getChannel(orderDto.getActualDriverUuid()).getData()) {
                    String driMsgNo = "乘客尾号：" + StringUtils.right(passenger.getMobile(), 4) + "的订单已被乘客取消，取消原因：" + cancelMsg;
                    SendMessageUtils.generalSend(actDriver.getMobile(), driMsgNo, orderDto.getAppid());
                }
                orderTrackMileageService.statusCycle(actDriver.getAppid(), actDriver.getUuid(), orderUuid, actDriver.getCarUuid(), DriverStatusCycleDto.ACTION_CANCEL);
                //取消订单时，解绑隐私号
                CompletableFuture.runAsync(() -> orderSecretNoService.unbind(orderDto.getUuid()));
                //订单取消后解除司机锁定
                removeDriverLock(orderDto.getActualDriverUuid());
                return ResponseData.buildSuccessResponse("取消订单成功", Boolean.TRUE);
            }
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，正在进行中的订单无法取消");
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，订单状态异常");
    }

    @Override
    public ResponseData<Boolean> driConfirmCancel(String orderUuid, String cancelMsg, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未检索到订单");
        }
        CarModelValuationDto carValuationDto = orderFareService.getCarModelValuationDto(orderDto.getUuid()).getData();
        if (carValuationDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未检索到车辆信息");
        }
        if (ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，初始化的订单不能取消");
        }
        if (ORDER_MAIN_STATUS_DONE.equals(orderDto.getMainStatus())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，待支付的订单不能取消");
        }
        if (ORDER_MAIN_STATUS_CANCEL.equals(orderDto.getMainStatus())) {
            //如果订单大状态为取消，并且小状态为司机取消，返回成功，否则返回订单状态异常
            if (ORDER_STATUS_DRIVER_CANCEL.equals(orderDto.getSubStatus())) {
                return ResponseData.buildSuccessResponse("取消订单成功", Boolean.TRUE);
            } else {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，订单状态异常");
            }
        }
        if (ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            //乘客为待上车状态，司机都可以取消订单
            if (ORDER_STATUS_ARRIVE.compareTo(orderDto.getSubStatus()) == 0) {
                //插入取消原因到订单详情表
                ResponseData<Void> orderDetail4PasCancel = updOrderDetail4PasCancel(orderUuid, cancelMsg);
                if (!orderDetail4PasCancel.isSuccess()) {
                    return ResponseData.buildErrorResponse(orderDetail4PasCancel.getErrCode(), orderDetail4PasCancel.getMsg());
                }
                //插入取消产生的费用到价格表
                ResponseData<Void> orderFare4DriCancel = updOrderFare4DriCancel(orderDto, carValuationDto);
                if (!orderFare4DriCancel.isSuccess()) {
                    return ResponseData.buildErrorResponse(orderFare4DriCancel.getErrCode(), orderFare4DriCancel.getMsg());
                }

                //通知消息
                InformThreadPoolUtil.execute(new OrderStatusInformThread(orderDto, OrderEvent.SYS_CANCEL));

                //推送给乘客，已取消订单
                pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "行程已取消",
                        "司机已取消订单", ORDER_DRIVER_CANCEL, MapUtils.build("typeModule", orderDto.getTypeModule()));
                uploadTextResult(uploadText);
                //司机取消状态插入
                DriverVo actDriver = driverService.commonSelInfo(MapUtils.build("uuid", orderDto.getActualDriverUuid())).getData();
                orderTrackMileageService.statusCycle(actDriver.getAppid(), actDriver.getUuid(), orderUuid, actDriver.getCarUuid(), DriverStatusCycleDto.ACTION_CANCEL);
                //取消订单时，解绑隐私号
                CompletableFuture.runAsync(() -> orderSecretNoService.unbind(orderDto.getUuid()));
                //订单取消后解除司机锁定
                removeDriverLock(actDriver.getUuid());
                return ResponseData.buildSuccessResponse("取消订单成功", Boolean.TRUE);
            } else {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，未符合取消条件");
            }
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "取消订单失败，订单状态异常");
    }

    @Override
    public ResponseData<Void> removeDriverLock(String driverUuid) {
        if (StringUtils.isEmpty(driverUuid)) {
            return ResponseData.buildSuccessResponse(null);
        }
        try {
            if (redisLock.lock("LOCK" + ASSIGN_DRIVER_LOCK)) {
                Object obj = redisCacheService.get(ASSIGN_DRIVER_LOCK);
                if (obj != null) {
                    List<String> lockedDriverList = (List<String>) obj;
                    lockedDriverList.remove(driverUuid);
                    if (CollectionUtils.isNotEmpty(lockedDriverList)) {
                        redisCacheService.set(ASSIGN_DRIVER_LOCK, lockedDriverList);
                    } else {
                        redisCacheService.delete(ASSIGN_DRIVER_LOCK);
                    }
                }
            }
        } catch (InterruptedException e) {
            log.error("redisLock lock error,key:{}", "LOCK" + ASSIGN_DRIVER_LOCK);
        } finally {
            redisLock.unLock("LOCK" + ASSIGN_DRIVER_LOCK);
        }
        return ResponseData.buildSuccessResponse(null);
    }


    /**
     * <p>保存司机取消，乘客迟到所产生的费用</p>
     * <p>司机取消订单没有取消费用，只有超时等待费</p>
     *
     * @param orderDto        订单信息
     * @param carValuationDto 车辆信息
     * @return
     */
    private ResponseData<Void> updOrderFare4DriCancel(OrderDto orderDto, CarModelValuationDto carValuationDto) {
        //获取司机到达上车地点时间
        OrderFareDto orderFareDto = orderFareService.get(MapUtils.build("orderUuid", orderDto.getUuid())).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单价格详情失败");
        }
        if (orderFareDto.getDriArrTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机到达上车地点的时间");
        }
        long driverArriveTime = orderFareDto.getDriArrTime().getTime();
        //获取出发时间
        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderDto.getUuid())).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单附加详情失败");
        }
        if (orderDetailDto.getDeparTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单出发时间");
        }
        Date date = new Date();
        long departTime = orderDetailDto.getDeparTime().getTime();
        //免费等待时长
        double freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime();
        //获取等待的分钟数(如果司机提早到达，则以出发时间开始算起，如果司机迟到，则以司机到达的时间开始算)
        double waitTime = 0;
        if (driverArriveTime <= departTime) {
            waitTime = (date.getTime() - departTime) / (60 * 1000d);
        } else {
            waitTime = (date.getTime() - driverArriveTime) / (60 * 1000d);
        }
        if (waitTime <= freeWaitTime) {
            //如果乘客未迟到（等待时长未超过免费等待时长）
            //更新主表，不产生取消费用
            updateOrderStatus(orderDto, ORDER_STATUS_DRI_CANCEL_WAIT_FREE, ORDER_MAIN_STATUS_CANCEL);
            return ResponseData.buildSuccessResponse("无超时等待费", null);
        }
        int beyondTime = (int) Math.ceil(waitTime - freeWaitTime);
        double beyondWaitFare = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
//        BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondTime).setScale(1, BigDecimal.ROUND_HALF_UP);
        BigDecimal bd = BigDecimal.valueOf(beyondWaitFare * beyondTime).setScale(2, BigDecimal.ROUND_HALF_UP);
        //更新订单价格表详情
        OrderFareDto updOrderFareDto = new OrderFareDto();
        updOrderFareDto.setUuid(orderFareDto.getUuid());
        updOrderFareDto.setWaitFare(bd.doubleValue());
        //实际行驶里程
        updOrderFareDto.setTripDistance(new Double(0));
        //实际行驶时长
        updOrderFareDto.setTripDuration(0);
        updOrderFareDto.setWaitDuration(beyondTime);
        updOrderFareDto.setTotalFare(orderFareDto.getTotalFare() == null ? bd.doubleValue() : (orderFareDto.getTotalFare() + bd.doubleValue()));
//        updOrderFareDto.setOrderFare(BigDecimal.valueOf(updOrderFareDto.getTotalFare()).setScale(1, BigDecimal.ROUND_HALF_UP));
        updOrderFareDto.setOrderFare(BigDecimal.valueOf(updOrderFareDto.getTotalFare()).setScale(2, BigDecimal.ROUND_HALF_UP));
        orderFareService.saveOrUpdate(updOrderFareDto);
        //更新主表
        if (bd.doubleValue() > 0.0) {
            updateOrderStatus(orderDto, ORDER_STATUS_PAY_WAIT_DRI_CANCEL, ORDER_MAIN_STATUS_DONE);
        } else {
            //有超时等待费用，但是为0 的时候时候直接取消订单，无需跳到支付的状态
            updateOrderStatus(orderDto, ORDER_STATUS_DRI_CANCEL_WAIT_FREE, ORDER_MAIN_STATUS_CANCEL);
        }
        return ResponseData.buildSuccessResponse("有超时等待费", null);
    }


    /**
     * 保存乘客取消所产生的费用
     *
     * @param orderDto        订单信息
     * @param carValuationDto 计费信息
     * @return
     */
    private ResponseData<Void> updOrderFare4PasCancel(OrderDto orderDto, CarModelValuationDto carValuationDto) {
        //获取司机到达上车地点时间
        Map<String, Object> build = MapUtils.build("orderUuid", orderDto.getUuid());
        OrderFareDto orderFareDto = orderFareService.get(build).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单价格详情失败");
        }
        if (orderFareDto.getDriArrTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到司机到达上车地点的时间");
        }
        //获取出发时间
        OrderDetailDto orderDetailDto = orderDetailService.get(build).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单附加详情失败");
        }
        if (orderDetailDto.getDeparTime() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到出发时间");
        }
        //免费等待时长（分钟）
        int freeWaitTime = carValuationDto.getFreeWaitTime() == null ? 0 : carValuationDto.getFreeWaitTime();
        //超出免费等待时长的费用（元/分钟）
        double beyondWaitFare = carValuationDto.getBeyondWaitFare() == null ? 0 : carValuationDto.getBeyondWaitFare();
        double cancelFare = carValuationDto.getOwnCancelFare() == null ? 0d : carValuationDto.getOwnCancelFare();
        BigDecimal totalFare = orderFareDto.getTotalFare() == null ? BigDecimal.ZERO : BigDecimal.valueOf(orderFareDto.getTotalFare());
        long millis = System.currentTimeMillis();
        long driArrTime = orderFareDto.getDriArrTime().getTime();
        long departTime = orderDetailDto.getDeparTime().getTime();
        BigDecimal waitFare = BigDecimal.ZERO;
        //等待分钟数
        int waitTime;
        int waitTimeAmountSeconds;
        if (driArrTime > departTime) {
            //司机晚于出发时间到达，超时等待时间以司机到达时间开始算起
            waitTime = (int) Math.ceil((millis - driArrTime) / (60 * 1000d));
            waitTimeAmountSeconds = (int) Math.ceil((millis - driArrTime) / 1000);
            //如果预约订单司机迟到，则不收取取消费用
            if (CommonConstant.TYPE_TIME_APPIONT == orderDto.getTypeTime()) {
                cancelFare = 0d;
            }
        } else {
            //司机早于出发时间到达，超时等待时间以出发时间开始算起
            waitTime = (int) Math.ceil((millis - departTime) / (60 * 1000d));
            waitTimeAmountSeconds = (int) Math.ceil((millis - departTime) / 1000);
        }
        //获取超时等待费用
        if (waitTime > freeWaitTime) {
            waitFare = BigDecimal.valueOf(beyondWaitFare).multiply(BigDecimal.valueOf(waitTime - freeWaitTime))
//                    .setScale(1, BigDecimal.ROUND_HALF_UP);
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        //计算总费用
//        totalFare = totalFare.add(waitFare).add(BigDecimal.valueOf(cancelFare)).setScale(1, BigDecimal.ROUND_HALF_UP);
        totalFare = totalFare.add(waitFare).add(BigDecimal.valueOf(cancelFare)).setScale(2, BigDecimal.ROUND_HALF_UP);
        OrderFareDto updOrderFareDto = new OrderFareDto();
        updOrderFareDto.setUuid(orderFareDto.getUuid());
        //实际行驶里程
        updOrderFareDto.setTripDistance(0d);
        //实际行驶时长
        updOrderFareDto.setTripDuration(0);
        updOrderFareDto.setWaitDuration(waitTime - freeWaitTime);
        updOrderFareDto.setWaitFare(waitFare.doubleValue());
        updOrderFareDto.setWaitTimeSeconds(waitTimeAmountSeconds);
        updOrderFareDto.setCancelFare(cancelFare);
        updOrderFareDto.setTotalFare(totalFare.doubleValue());
        //乘客未上车，车费为0
        updOrderFareDto.setOrderFare(BigDecimal.ZERO);
        orderFareService.saveOrUpdate(updOrderFareDto);
        //更新主表
        if (updOrderFareDto.getTotalFare() == 0) {
            updateOrderStatus(orderDto, ORDER_STATUS_PASS_CANCEL_WAIT_FREE, ORDER_MAIN_STATUS_CANCEL);
        } else {
            updateOrderStatus(orderDto, ORDER_STATUS_PAY_WAIT_PASS_CANCEL, ORDER_MAIN_STATUS_DONE);
        }
        return ResponseData.buildSuccessResponse("更新费用成功", null);
    }

    /**
     * 乘客取消订单，插入取消原因到订单详情表
     */
    private ResponseData<Void> updOrderDetail4PasCancel(String orderUuid, String cancelMsg) {
        //如果取消原因有值，更新记录
        OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderUuid)).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单详情");
        }
        OrderDetailDto updOrderDetailDto = new OrderDetailDto();
        updOrderDetailDto.setUuid(orderDetailDto.getUuid());
        updOrderDetailDto.setCancelReason(cancelMsg);
        updOrderDetailDto.setCancelTime(new Date());
        updOrderDetailDto.setUpdateOn(new Date());
        orderDetailService.saveOrUpdate(updOrderDetailDto);
        return ResponseData.buildSuccessResponse("操作成功", null);
    }

    @Override
    public void updateOrderStatus(OrderDto orderDto, Integer subStatus, Integer mainStatus) {
        if (orderDto != null) {
            OrderDto newOrderDto = new OrderDto();
            newOrderDto.setUuid(orderDto.getUuid());
            newOrderDto.setSubStatus(subStatus);
            newOrderDto.setMainStatus(mainStatus);
            saveOrUpdate(newOrderDto);
        }
    }

    @Override
    public ResponseData<Boolean> updOrderFare(String orderUuid, Double actualFare, Double otherFare) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null != orderDto) {
            //设置订单状态为未支付
            orderDto.setPayStatus(Constants.ORDER_PAY_STATUS_UNPAY);
            orderMapper.edit(orderDto);
            //更新订单表，子状态改为500：司机确认费用，等待乘客支付, 主状态改为3：行程结束、待支付
            updateOrderStatus(orderDto, ORDER_STATUS_FARE_CONFIRM, ORDER_MAIN_STATUS_DONE);
            //保存金额到订单价格详情表
            ResponseData<Boolean> updFare = orderFareService.updFare(orderUuid, actualFare, otherFare);
            if (!updFare.isSuccess()) {
                return ResponseData.buildErrorResponse(updFare.getErrCode(), updFare.getMsg());
            }
            //推送给乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(),
                    "保存成功", "保存金额成功", ORDER_DRIVER_CONFIRM_FARE, MapUtils.build("typeModule", orderDto.getTypeModule()));
            return ResponseData.buildSuccessResponse("更改订单状态成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "更改订单状态失败");
    }

    @Override
    public ResponseData<Boolean> updArrive(String orderUuid, Double tripDistance, String tripRecording, OrderDetailDto destination, String uploadText) {
        if (tripDistance == null) {
            log.info("订单{}修改状态失败，行程公里数不能为空", orderUuid);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败，行程公里数不能为空");
        }
        OrderDto orderDto = findOrder(orderUuid);
        if (null == orderDto) {
            log.info("订单{}修改状态失败，找不到该订单", orderUuid);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "修改状态失败，找不到该订单");
        }
        if (ORDER_STATUS_START.equals(orderDto.getSubStatus()) && ORDER_MAIN_STATUS_DOING.equals(orderDto.getMainStatus())) {
            OrderDetailDto orderDetailDto = orderDetailService.get(MapUtils.build("orderUuid", orderUuid)).getData();
            if (orderDetailDto == null) {
                log.info("订单{}获取不到订单详情信息", orderUuid);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单详情信息");
            }
            // 保存录音信息
            if (StringUtils.isNotEmpty(tripRecording)) {
                OrderDetailDto updDetailDto = new OrderDetailDto();
                updDetailDto.setUuid(orderDetailDto.getUuid());
                updDetailDto.setTripRecording(tripRecording);
                updDetailDto.setUpdateOn(new Date());
                CompletableFuture.runAsync(() -> orderDetailService.edit(updDetailDto));
            }
            //更改费用表记录
            OrderFareDto orderFareDto = orderFareService.get(MapUtils.build("orderUuid", orderUuid)).getData();
            if (orderFareDto == null) {
                log.info("订单{}获取不到订单费用信息", orderUuid);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单费用信息");
            }
            //获取车型计费方式
            CarModelValuationDto carValuationDto = carModelValuationService.get(orderFareDto.getCarModelValuationUuid()).getData();
            if (carValuationDto == null) {
                log.info("订单{}获取不到计价规则", orderUuid);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到数据");
            }
            //计算里程前先上传点
            if (!uploadTextResult(uploadText)) {
                log.info("订单{}上传定位点失败", orderUuid);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "上传定位点失败，请重试");
            }
            //计算里程
            tripDistance = calculateDistance(orderUuid, tripDistance, orderDto, orderFareDto, orderDetailDto, uploadText);
            log.info("订单{}计算里程结果 tripDistance:{}", orderUuid, tripDistance);
            ResponseData<Boolean> saveTotalFare = orderFareService.saveTotalFare(carValuationDto, orderFareDto,
                    tripDistance, uploadText, orderDetailDto);
            if (!saveTotalFare.isSuccess()) {
                log.info("订单{}保存估价失败", orderUuid);
                saveTotalFare.setMsg("保存估价失败，请重试");
                return saveTotalFare;
            }
            //租车更新目的地信息
            if (orderDto.getTypeTime() == CommonConstant.TYPE_TIME_DAILY_RENTAL || orderDto.getTypeTime() == CommonConstant.TYPE_TIME_HALF_DAILY_RENTAL) {
                destination.setUuid(orderDetailDto.getUuid());
                orderDetailService.edit(destination);
            }
            //更改主表订单状态
            updateOrderStatus(orderDto, ORDER_STATUS_ARRIVED, null);
            //推送给乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(),
                    "达到目的地", "达到目的地", ORDER_DRIVER_ARRIVE_DESTINATION, MapUtils.build("typeModule", orderDto.getTypeModule()));
            // 因为与主逻辑无关 所以异步统计里程
            ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                    driverStatusCycleService,
                    locationService,
                    orderDto.getAppid(),
                    orderDto.getActualDriverUuid(), orderUuid,
                    orderDto.getCarUuid(),
                    // 服务
                    DriverStatusCycleDto.ACTION_SERVICE_OVER, tripDistance));

            //通知消息
            InformThreadPoolUtil.execute(new OrderStatusInformThread(orderDto, OrderEvent.CHARGE_STOP));
            return ResponseData.buildSuccessResponse("修改状态成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());

    }

    /**
     * 计算里程
     *
     * @param orderUuid       String
     * @param appGaodeDitance double
     * @param orderDto
     * @param orderFareDto    OrderFareDto
     * @param orderDetailDto  OrderDetailDto
     */
    private double calculateDistance(String orderUuid, double appGaodeDitance, OrderDto orderDto,
                                     OrderFareDto orderFareDto, OrderDetailDto orderDetailDto, String uploadText) {
        log.info("订单{}开始调用高德计算里程", orderUuid);
        double tripDistance = 0.0D;
        //按照乘客出发时间到当前
        TrsearchParam trsearchParam = new TrsearchParam();
        trsearchParam.setStarttime(orderFareDto.getPasArrTime());
        trsearchParam.setEndtime(new Date());
        ResponseData<List<TrackVo>> traceCheck = distanceService.gaodeTraceCheck(orderDto.getActualDriverUuid(),
                orderUuid, trsearchParam);
        if (traceCheck.isSuccess() && CollectionUtils.isNotEmpty(traceCheck.getData())) {
            TrackVo trackVo = traceCheck.getData().get(0);
            tripDistance = trackVo.getDistance().doubleValue() / 1000.0;
        }
        log.info("------------------------orderUuid：{},猎鹰计算里程:{}", orderUuid, tripDistance);
        //这边如果里程还是0，就搜索实际起点和终点来预估距离
        if (tripDistance < 0.1d) {
            DriverLocation ckscLocation = locationService.getOrderPointByPositionType(orderUuid, "CKSC").getData();
            if (ckscLocation != null) {
                double ckscLng = ckscLocation.getCoordinate().getLng();
                double ckscLat = ckscLocation.getCoordinate().getLat();
                //获取下车点
                UploadLocationMessage uploadLocationMessage = null;
                try {
                    uploadLocationMessage = JsonUtils.readValue(uploadText, UploadLocationMessage.class);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                double ckxcLng = uploadLocationMessage.getLng();
                double ckxcLat = uploadLocationMessage.getLat();
                //根据经纬度到高德获取预估里程
                DrivingNearestVo drivingNearestVO = distanceService.getDrivingNearest(String.valueOf(ckscLng), String.valueOf(ckscLat),
                        String.valueOf(ckxcLng), String.valueOf(ckxcLat)).getData();
                tripDistance = drivingNearestVO.getDistance() / 1000.0;
                log.info("-------------------------orderUuid：{},实际上下车点里程:{}", orderUuid, tripDistance);
            } else {
                if (tripDistance == 0d && appGaodeDitance != 0) {
                    //如果预估出来还是0,并且高德里程不为0，则取高德计算的里程
                    tripDistance = appGaodeDitance;
                    log.info("------------------------orderUuid：{},手机端上传的高德里程:{}", orderUuid, tripDistance);
                } else {
                    tripDistance = orderDetailDto.getPlanTrip();
                    log.info("------------------------orderUuid：{},手机端下单时预估的高德里程:{}", orderUuid, tripDistance);
                }
            }
        }
        //保存一下高德里程到fare表
        orderFareDto.setGaodeDistance(appGaodeDitance);
        return tripDistance;
    }

    @Override
    public ResponseData<Boolean> confirmFare(String orderUuid, String uploadText) {
        OrderDto orderDto = findOrder(orderUuid);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单");
        }
        if (ORDER_STATUS_ARRIVED.compareTo(orderDto.getSubStatus()) != 0) {
            return ResponseData.buildErrorResponse(GRAB_ERROR_1100.getCode(), GRAB_ERROR_1100.getMsg());
        }
        //设置订单状态为未支付
        orderDto.setPayStatus(Constants.ORDER_PAY_STATUS_UNPAY);
        orderMapper.edit(orderDto);
        updateOrderStatus(orderDto, ORDER_STATUS_FARE_CONFIRM, ORDER_MAIN_STATUS_DONE);
//        updateOrderStatus(orderDto, ORDER_STATUS_FARE_CONFIRM, ORDER_MAIN_STATUS_DONE);
        //顺路订单关闭司机顺路状态
        if (CommonConstant.SAME_WAY_ORDER_TRUE == ParamUtil.defaultIfNull(orderDto.getSameWayOrder(), 0)) {
            DriverDto driverDto = new DriverDto();
            driverDto.setUuid(orderDto.getActualDriverUuid());
            driverDto.setSameWayModel(CommonConstant.SAME_WAY_MODEL_OFF);
            driverService.edit(driverDto);
        }

        //更新orderFare表的arrive状态，方便催款按钮时间判断
        Map<String, Object> fareMap = MapUtils.build(4);
        fareMap.put("orderUuid", orderUuid);
        OrderFareDto orderFareDto = orderFareService.get(fareMap).getData();
        if (orderFareDto != null) {
            orderFareDto.setConfirmTime(new Date());
            //保存确认费用时的订单费用
            orderFareDto.setConfirmOrderFare(orderFareDto.getLatestOrderFare());
            //保留运价的静态数据
            updateOrderStaticDataOnConfirmFare(orderFareDto);
            orderFareService.saveOrUpdate(orderFareDto);
        }
        //推送给乘客
        pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(),
                "达到目的地", "到达目的地，请及时支付车费", ORDER_DRIVER_CONFIRM_FARE, MapUtils.build("typeModule", orderDto.getTypeModule()));
        uploadTextResult(uploadText);
        SecretNoParam secretNoParam = new SecretNoParam();
        secretNoParam.setOrderUuid(orderUuid);
        orderSecretNoService.updateExpire(secretNoParam);
        //解绑隐私小号
        orderSecretNoService.unbind(orderUuid);
        //订单结束后解除司机锁定
        removeDriverLock(orderDto.getActualDriverUuid());
        //通知消息
        InformThreadPoolUtil.execute(new OrderStatusInformThread(orderDto, OrderEvent.OTHER_FARE));
        return ResponseData.buildSuccessResponse("确认费用成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Integer> getCount(Map<String, Object> params) {
        return ResponseData.buildSuccessResponse(this.orderMapper.getCount(params));
    }

    @Override
    public ResponseData<PageList<JsonOrderListVo>> queryPageList(Map<String, Object> map, ApiPageParam pageParam) {
        PageBounds pageBounds = new PageBounds(pageParam.getNowPage(), pageParam.getPageSize());
        return ResponseData.buildSuccessResponse(orderMapper.queryPageList(map, pageBounds));
    }

    @Override
    public ResponseData<ApiDriverOrderVo> statisticDriverOrder(String driUuid, Integer type, Date startDate, Date endDate) {
        return ResponseData.buildSuccessResponse(orderMapper.statisticDriverOrder(driUuid, type, startDate, endDate));
    }


    @Override
    public ResponseData<Map<String, Object>> queryHomePage(String driverUuid, String appid) {
        Map<String, Object> map = MapUtils.build();
        //获取当天已完成的订单数
        map.put("actualDriverUuid", driverUuid);
        map.put("appid", appid);
        Integer totalOrderDone = orderMapper.queryTodayOrderDone4Driver(map);
        Double totalIncome;
        map.clear();
        map.put("driverUuid", driverUuid);
        map.put("today", "1");
        BigDecimal income = financeOrderService.findIncomeByTime(map).getData();
        totalIncome = income.doubleValue();
        //获取用车时间在半小时以内的最新一个预约订单
        JsonOrderListVo jsonOrderListVo = orderMapper.queryAppointOrderIn30Minute(map);
        //现在改成使用
        map.clear();
        map.put("totalOrderDone", totalOrderDone == null ? 0 : totalOrderDone);
        map.put("totalIncome", totalIncome);
        map.put("orderList", jsonOrderListVo);
        map.put("date", new Date());
        //获取出车时间
        Integer onWorkTime = driverStatusCycleService.queryWorkTimeSum(driverUuid, null).getData();
        //获取出车时间（毫秒）
        map.put("onWorkTime", onWorkTime * 1000);
        return ResponseData.buildSuccessResponse(map);
    }

    @Override
    public ResponseData<Map<String, Object>> getAppointmentToBeStart(String driverUuid) {
        Map<String, Object> params = MapUtils.build();
        params.put("actualDriverUuid", driverUuid);
        params.put("mainStatus", ORDER_MAIN_STATUS_DOING);
        params.put("subStatus", ORDER_STATUS_CONFIRM);
        params.put("typeTimeOrSend", 1);
        List<JsonOrderListVo> orderList = orderMapper.getAllByStatus(params);
        params.clear();
        if (orderList != null && orderList.size() > 0) {
            for (JsonOrderListVo jsonOrder : orderList) {
                Date date = new Date();
                Date departTime = jsonOrder.getDeparTime() == null ? date : jsonOrder.getDeparTime();
                if (!DateUtils.compareByMins(date, departTime, 30)) {
                    params.put("orderUuid", jsonOrder.getUuid());
                    params.put("deparTime", jsonOrder.getDeparTime());
                    params.put("originAddress", jsonOrder.getOriginAddress());
                    params.put("destAddress", jsonOrder.getDestAddress());
                }
            }
        }
        return ResponseData.buildSuccessResponse(params);
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> getAppointmentList(Map<String, Object> paraMap) {
        Map<String, Object> params = MapUtils.build(8);
        params.put("actualDriverUuid", paraMap.get("driverUuid"));
        params.put("mainStatus", ORDER_MAIN_STATUS_DOING);
        params.put("subStatus", ORDER_STATUS_CONFIRM);
        params.put("typeTimeOrSend", 1);
        return ResponseData.buildSuccessResponse(orderMapper.getAppointmentList(params));
    }

    @Override
    public ResponseData<Map<String, Object>> getFreshAppointmentCount(Map<String, Object> paraMap) {
        //获取订单信息
        Map<String, Object> resultMap = MapUtils.build(3);
        ResponseData<List<JsonOrderListVo>> ajaxList = getOrderList(paraMap);
        if (!ajaxList.isSuccess()) {
            return ResponseData.buildSuccessResponse(MapUtils.build());
        }
        List<JsonOrderListVo> orderList = ajaxList.getData();
        resultMap.put("orderCount", orderList == null ? 0 : orderList.size());
        return ResponseData.buildSuccessResponse(resultMap);
    }

    @Override
    public ResponseData<List<JsonOrderListVo>> getFreshAppointmentDetail(Map<String, Object> paraMap) {
        //获取订单信息
        return getOrderList(paraMap);
    }

    /**
     * 获取订单信息
     *
     * @param paraMap
     * @return
     */
    private ResponseData<List<JsonOrderListVo>> getOrderList(Map<String, Object> paraMap) {
        Map params = MapUtils.build(8);
        params.put("driverUuid", paraMap.get("driverUuid"));
        params.put("mainStatus", ORDER_MAIN_STATUS_INITIAL);
        params.put("subStatus", ORDER_STATUS_WAIT);
        params.put("typeInteractive", NEW_ORDER_TYPE_INTERACTIVE_SNATCH);
        return ResponseData.buildSuccessResponse("获取可抢预约单明细成功", orderMapper.getFreshAppointmentDetail(params));
    }

    @Override
    public ResponseData<List<OrderDto>> getCancelPassengerOrder(String appid) {
        return ResponseData.buildSuccessResponse(orderMapper.getCancelPassengerOrder());
    }


    @Override
    public ResponseData<ApiOrderInfoVo> getOrderInfo(String orderUuid) {
        ApiOrderInfoVo orderInfo = orderMapper.getOrderInfo(orderUuid);
        if (orderInfo == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单信息失败");
        }
        Date date = new Date();
        //发单正序
        orderInfo.setCountdown(date.getTime() - orderInfo.getCreateOn().getTime());
        // 如果是预约订单，且行程已确定
        if (orderInfo.getTypeTime().compareTo(CommonConstant.TYPE_TIME_APPIONT) == 0
                && ORDER_STATUS_CONFIRM.compareTo(orderInfo.getSubStatus()) == 0) {
            orderInfo.setCountdown(orderInfo.getDeparTime().getTime() - date.getTime());
        }
        //增加是否超过24小时
        orderInfo.setOverTime(0);
        if (orderInfo.getDeparTime() != null && DateUtils.compareByDay(date, orderInfo.getDeparTime(), 1)) {
            orderInfo.setOverTime(1);
        }
        // 如果订单有确定司机的情况下，做以下判断
        if (StringUtils.isNotEmpty(orderInfo.getDriverUuid())) {
            // （预约单）司机是否可以出发去接乘客
            // 当该订单是最近一条预约订单，且距离出发时间1小时内时才可以
            Map<String, Object> srhMap = MapUtils.build(3);
            srhMap.put("actualDriverUuid", orderInfo.getDriverUuid());
            srhMap.put("typeTime", CommonConstant.TYPE_TIME_APPIONT);
            // 检索司机所有进行中预约订单
            List<JsonOrderListVo> listOrderDoing = orderMapper.queryOrderDoing(srhMap);
            // 默认值：不可以出发去接乘客
            orderInfo.setCanPickUp(0);
            // 如果存在进行中订单
            if (listOrderDoing != null && listOrderDoing.size() > 0) {
                // 该订单是最近一条预约订单
                if (listOrderDoing.get(0) != null && orderUuid.equals(listOrderDoing.get(0).getUuid())) {
                    // 距离出发时间1小时内
                    if (orderInfo.getDeparTime().getTime() - date.getTime() <= 60 * 60 * 1000) {
                        // 可以出发去接乘客
                        orderInfo.setCanPickUp(1);
                    }
                }
            }
            // 司机是否可以催促乘客付款
            // 当乘客未付款超过10分钟可按
            // 默认值：不可以催促乘客付款
            orderInfo.setCanHurryPay(0);
            if (ORDER_MAIN_STATUS_DONE.compareTo(orderInfo.getMainStatus()) == 0) {
                Map<String, Object> fareMap = MapUtils.build(1);
                fareMap.put("orderUuid", orderUuid);
                OrderFareDto orderFareDto = orderFareService.get(fareMap).getData();
                // 当乘客未付款超过10分钟可按
                if (orderFareDto != null && orderFareDto.getArriveTime() != null
                        && (date.getTime() - orderFareDto.getArriveTime().getTime() > 10 * 60 * 1000)) {
                    orderInfo.setCanHurryPay(1);
                }
            }
            //获取司机所有成功单数
            List<OrderDto> orderDtos = orderMapper.driverAccomplishOrder(orderInfo.getDriverUuid());
            if (orderDtos.size() != 0) {
                orderInfo.setDriverOrderCount(orderDtos.size());
            }
        }
        //日租半日租拼接订单标题
        if (CommonConstant.TYPE_TIME_DAILY_RENTAL == orderInfo.getTypeTime() || CommonConstant.TYPE_TIME_HALF_DAILY_RENTAL == orderInfo.getTypeTime()) {
            CarModelValuationDto rentFareRuleDto = carModelValuationService.get(MapUtils.build("uuid", orderInfo.getCarModelValuationUuid())).getData();
            if (rentFareRuleDto != null) {
                orderInfo.setTitle("包车" + rentFareRuleDto.getStartDuration() / 60 + "小时");
            }
        }
        //已完成订单计算实付金额
        if (orderInfo.getMainStatus().intValue() == ORDER_MAIN_STATUS_DONE) {
            //计算实付金额(已计算过调整费)
//            BigDecimal actualFare = BigDecimal.valueOf(orderInfo.getTotalFare()).setScale(1, BigDecimal.ROUND_HALF_UP);
            BigDecimal actualFare = BigDecimal.valueOf(orderInfo.getTotalFare()).setScale(2, BigDecimal.ROUND_HALF_UP);
            orderInfo.setActualFare(actualFare.doubleValue());

            //获取支付时订单的优惠券价格，车费为0时不获取优惠券
            BigDecimal latestOrderFare = orderInfo.getLatestOrderFare() == null ? new BigDecimal(0) : orderInfo.getLatestOrderFare();
            if (!isOrderCanceled(orderInfo.getSubStatus()) && (latestOrderFare.compareTo(BigDecimal.ZERO) == 1)) {
                ApiPasPayCouponParam couponParam = new ApiPasPayCouponParam();
                couponParam.setUserUuid(orderInfo.getPassengerUuid());
                couponParam.setBusinessType(orderInfo.getTypeTrip());
                couponParam.setTotalFare(orderInfo.getTotalFare());
                couponParam.setOriginCityUuid(orderInfo.getOriginCityUuid());
                PassengerCouponDto passengerCouponDto = passengerCouponService.findMinCoupon(couponParam).getData();
                if (passengerCouponDto != null) {
                    orderInfo.setCouponUuid(passengerCouponDto.getUuid());
                    orderInfo.setCouponFare(passengerCouponDto.getMoney());
                    //计算优惠劵抵扣金额
//                    BigDecimal couponMoney = BigDecimal.valueOf(orderInfo.getCouponFare()).setScale(1, BigDecimal.ROUND_HALF_UP);
                    BigDecimal couponMoney = BigDecimal.valueOf(orderInfo.getCouponFare()).setScale(2, BigDecimal.ROUND_HALF_UP);
                    orderInfo.setCouponFare(couponMoney.compareTo(actualFare) == 1 ? actualFare.doubleValue() : passengerCouponDto.getMoney());
                    //计算实付
//                    actualFare = actualFare.subtract(BigDecimal.valueOf(orderInfo.getCouponFare())).setScale(1, BigDecimal.ROUND_HALF_UP);
                    actualFare = actualFare.subtract(BigDecimal.valueOf(orderInfo.getCouponFare())).setScale(2, BigDecimal.ROUND_HALF_UP);
                    orderInfo.setActualFare(actualFare.compareTo(BigDecimal.ZERO) == 1 ? actualFare.doubleValue() : 0D);

                }
            }
        }
        log.info("----加载订单:{}详情位置点begin----", orderUuid);
        orderInfo.setTracePoints(getTracePoint(orderUuid, orderInfo.getDriverUuid(),
                orderInfo.getAppid(), orderInfo.getMainStatus()));
        return ResponseData.buildSuccessResponse("获取成功", orderInfo);
    }

    @Override
    public ResponseData<Void> extFareSettlement(PayVo payVo) {
        commissionProcessor.process(payVo);
        return ResponseData.buildSuccessResponse(null);
    }

    @Override
    public ResponseData<Map<String, Object>> getNoEvaluationOrder(String passengerUuid) {
        OrderDto orderDto = orderMapper.getNoEvaluationOrder(passengerUuid);
        boolean isExist = false;
        if (orderDto != null) {
            if (orderDto.getTypeModule() == BUSINESS_TYPE_PARCEL || orderDto.getTypeModule() == BUSINESS_TYPE_POOL) {
                if (orderDto.getJoinStatus() == ORDER_JOIN_STATUS_COMPLETED) {
                    isExist = true;
                }
            } else {
                if (OrderConstant.ORDER_STATUS_COMPLETE.equals(orderDto.getSubStatus())) {
                    isExist = true;
                }
            }
        }
        if (isExist) {
            return ResponseData.buildSuccessResponse(MapUtils.build("orderUuid", orderDto.getUuid()));
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未获取到订单");
    }
}
